iT邦幫忙

0

【You Don't Know JS: Scope & Closures】Chapter 2 筆記

WM 2019-03-01 17:49:481920 瀏覽
  • 分享至 

  • xImage
  •  

範疇有兩種模型:

  • 語彙範疇(Lexical Scope)
  • 動態範疇(Dynamic Scope)

Lex-time

語彙範疇(lexical scope)是在lexing time時期所定義的範疇。

換句話說,語彙範疇(lexical scope)是基於撰寫程式碼與程式區塊的實際位置所定義出來的。

example

function foo(a) {
    var b = a * 2;
    function bar(c) {
        console.log(a, b, c);
    }
    bar(b * 3);
}
foo(2); // 2 4 12

這個範例,有3個巢狀範疇(nested scopes):
https://ithelp.ithome.com.tw/upload/images/20181117/20112573bh6GWcqi0N.png
圖片來源:You Don't Know JS: Scope & Closures

  • scope1:全域範疇(global scope),裡面包含函式識別子(identifier) foo
  • scope2:函式foo的範疇,裡面包含參數a,區域變數b,函式bar
  • scope3:函式bar的範疇,裡面包含參數c

上面的圖並不是文氏圖(Venn diagram)。函式是無法同時存在於2個同層級的範疇

Look-ups

上面範例的執行過程:

  • Engine執行foo(2);,接著執行bar(b * 3);,最後執行console.log(a, b, c);
  • 這時需要對a,b,c執行RHS,所以Engine會從最內層的範疇開始搜尋。
  • a,b不在bar的範疇中,所以Engine會往外層的範疇(foo)找,並且找到。
  • 在呼叫bar的同時,b * 3的運算結果,作為引數,傳給c

Look-ups的動作,會在找到第一個符合的時候,就停止。

如果相同的識別子(identifier)名稱,分別定義在不同層級的範疇,會發生shadowing的情況。

「shadowing」意思是,內層範疇的識別子遮住了外層範疇同名的識別子(identifier),換句話說,只要在當時執行的範疇中找到符合的識別子(identifier),Look-ups的動作就會停止,不管外層是否有同名的識別子(identifier)都不會採用。

無論是否有shadowing的情況。Engine執行Look-ups的動作,都會從當下的範疇開始執行,視情況再往外層推移。

全域變數(global variables)本身會成為全域物件(global object)window的屬性。
我們可以藉由此特性,來存取被遮蔽的全域變數。

全域變數被遮蔽:

var c = 10;
function foo(a) {
    var b = a * 2;
    var c = 5;
    function bar(c) {
        console.log(a, b, c);
    }
    bar(c);
}
foo(2); //2 4 5

使用全域物件取得屬性值:

var c = 10;
function foo(a) {
    var b = a * 2;
    var c = 5;
    function bar(c) {
        console.log(a, b, c);
    }
    bar(window.c);
}
foo(2); //2 4 10

但如果被遮蔽的是非全域變數(non-global)的話,就無法使用此方法。

不管在何處呼叫函式,也不管是如何呼叫的,該函式在宣告(declaration)的時候,就已經決定其語彙範疇(lexical scope)了,不會改變。

重點整理

語彙範疇(Lexical scope)在宣告函式的時候就已經定義好了,也就是實際撰寫程式碼的位置。

不要使用eval & with。

參考來源:
https://ithelp.ithome.com.tw/upload/images/20181117/20112573OWtzPwjWh4.jpg

此為You Don't Know JS系列的筆記。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言